/** !Wrappers for C memory management functions with error checking

This module contains macros and functions that perform as wrappers
for standard C memory management functions, malloc, realloc and free.  The
wrapper functions check for incorrect use realloc and free, memory overrun
errors and double free errors.  If, at program termination, that memory has
not been properly free'd then error messages are written to stderr with the
unfreed memory allocations.  Logging of all memory management function calls
to stderr can be turned on to aid in debugging.  The wrappers can be 'turned
off' at compile time for zero overhead. */

#ifndef MX__DETK_ALLOC_HEADER
#   define MX__DETK_ALLOC_HEADER

#   include <stdlib.h>

#   ifdef __cplusplus
extren "C" {
#   endif

	/* Debugging defines ------------------------------------------------------- */
	/* If we are debugging, make sure the right modules are included */
#   ifdef MXDEBUG

/** !Turn on memory tracking
If this macro is defined the functions mx_malloc, mx_realloc and mx_free
are made to keep track of memory allocated and warn from common memory allocation
mistakes.  If this symbol is not defined then mx_malloc, mx_realloc and mx_free
just pass all arguments to the corresponding stdlib malloc, realloc, and free
function.  In this case no additional memory checking is done. */
#      define MXMODULE_ALLOC

#   endif

	/* Memory allocation ------------------------------------------------------- */
	void *mx__malloc(size_t bytes);
	void *mx__realloc(void *themem, size_t bytes);
	void mx__free(void *themem);

	void mx___fencecheck(void);
	const void *mx__alloc_walk(const void *ptr);
	void mx___alloc_tag(void *ptr, const char *file, const long line);

	extern unsigned int mx__alloc_bytes;
	extern unsigned int mx__alloc_allocs;

	extern const char *mx__alloc_file;
	extern long mx__alloc_line;
	extern long mx__alloc_size;

	/* Memory debugging on */
#   if defined(MXMODULE_ALLOC)

/** !Replacement for stdlib malloc
This function is a wrapper for malloc().  If MXMODULE_ALLOC is defined then
this function keeps track of memory and warns about possible memory allocation
problems. */
#      define mx_malloc          (mx__alloc_file = __FILE__, mx__alloc_line = __LINE__, mx__malloc)

/** !Replacement for stdlib realloc
This function is a wrapper for realloc().  If MXMODULE_ALLOC is defined then
this function keeps track of memory and warns about possible memory allocation
problems. */
#      define mx_realloc         (mx__alloc_file = __FILE__, mx__alloc_line = __LINE__, mx__realloc)

/** !Replacement for stdlib free
This function is a wrapper for free().  If MXMODULE_ALLOC is defined then
this function keeps track of memory and warns about possible memory allocation
problems. */
#      define mx_free            (mx__alloc_file = __FILE__, mx__alloc_line = __LINE__, mx__free)

/** !Tag an allocation (debug)
This macro tags a pointer to memory with the current filename and source line.
If the pointer does not exist the the current allocation list then this macro does nothing.
If memory debugging is off (MXMODULE_ALLOC undefined or NDEBUG is defined) then
this macro compiles to nothing. */
#      define MXDEBUG_ALLOCTAG(p) do { mx___alloc_tag((p), __FILE__, __LINE__); } while (0)

/** !Check all allocations
This macro causes all allocations to be checked for over/under writing.
If memory debugging is off (MXMODULE_ALLOC undefined or NDEBUG is defined) then
this macro compiles to nothing. */
#      define MXDEBUG_ALLOCCHECK() mx___fencecheck()

	/* No memory debugging */
#   else
#      define mx_malloc          malloc
#      define mx_realloc         realloc
#      define mx_free            free
#      define MXDEBUG_ALLOCTAG(p)
#      define MXDEBUG_ALLOCCHECK()
#   endif

#   ifdef __cplusplus
}
#   endif
#endif

/*
   DEDS
   Data structures and utility functions for C
   Copyright (C) 2006 Douglas Eleveld

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
